#include "SharedFileName.h"
#include <fstream>
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <set>
#include <sstream>
#include <unordered_map>
#include <map>
#include <vector>
#include <queue>  
#include <sqlite3.h> 
#include <algorithm>
#include <time.h>
using namespace std;

void GenerateInterval(vector<double>& all_freq_value,int num_elem_interval, string out_dir){
	int num_rows = all_freq_value.size();
	vector<double> interval_start_value;
	vector<int> interval_size;

	int val_idx = num_rows-1;
	while(val_idx >= 0){
		int size = 0;
		double temp_val = all_freq_value[val_idx];
		interval_start_value.push_back(temp_val);
		for(int i = 0; i < num_elem_interval; i++){
			if(val_idx < 0) break;
			temp_val = all_freq_value[val_idx];
			size++;
			val_idx--;
		}

		if(val_idx < 0){
			interval_size.push_back(size);
			break;
		}

		// make interval distinct
		while(temp_val == all_freq_value[val_idx]){
			size++;
			val_idx--;
			if(val_idx < 0) break;
		}

		if(val_idx < 0){
			interval_size.push_back(size);
			break;
		}
		interval_size.push_back(size);
	}

	cout << "interval size: " << num_elem_interval << endl;
	for(int i = 0; i < interval_start_value.size(); i++){
		cout << "interval " << i << ":[" << interval_start_value[i] << "," << (i == interval_start_value.size()-1 ? 1 : interval_start_value[i+1])
			<< "] with size: " << interval_size[i] << endl;
	}


	ofstream intervalFile(out_dir.append(sample_freq_interval),ios::out);
	for(int i = 0; i < interval_start_value.size(); i++){
		intervalFile << interval_start_value[i] << " ";
	}
	intervalFile << endl;
	intervalFile.close();
}

void ComputeFreqInterval(string out_dir){
	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;

	string db_name(out_dir);
	db_name.append(sample_database_name);

	/* Open database */
	cout << "open db in cmpute frequency: " << db_name << endl;
	rc = sqlite3_open(db_name.c_str(), &db);
	if( rc ){
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		exit(0);
	}else{
		fprintf(stdout, "Opened database successfully\n");
	}


	// open transction
	sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &zErrMsg);

	vector<double> all_freq_value;
	int num_rows = 0;
	stringstream sql;
	sql << "select " << term_freq_name << " from  " << doc_term_table_name << ";";
	sqlite3_stmt *statement;
	if (sqlite3_prepare(db, sql.str().c_str(), -1, &statement, 0) == SQLITE_OK ) 
	{
		int res = 0;
		while ( 1 )         
		{
			res = sqlite3_step(statement);

			if ( res == SQLITE_ROW ) 
			{
				all_freq_value.push_back(atof((char*)sqlite3_column_text(statement, 0)));
				num_rows++;
				if(num_rows  % 1000000 == 0){
					cout << "read " << num_rows / 1000000 << "M rows" << endl;
					//break;
				}
			}

			if ( res == SQLITE_DONE || res==SQLITE_ERROR)    
			{
				cout << "done " << endl;
				break;
			}    
		}
	}
	
	// close transction
	sqlite3_exec(db, "END TRANSACTION", NULL, NULL, &zErrMsg);
	sqlite3_close(db);

	cout << "finish reading" << endl;
	sort(all_freq_value.begin(),all_freq_value.end());
	GenerateInterval(all_freq_value,FREQUENCY_INTERVAL_LENGTH,out_dir);
}

int main(int argc, char *argv[]){

	if(argc != 2){
		cout << "wrong arguments for " << argv[0] << endl;
		cout << "1. input directory" << endl;
		exit(1);
	}

	string in_dir(argv[1]);

	ComputeFreqInterval(in_dir);
}